#include "stdafx.h"

#include "gtest/gtest.h"
#include "PlayerManager.h"
#include "INextPlayer.h"

TEST(domino, PlayerManager_HappyDay) {
	_CrtMemState _ms;
	_CrtMemCheckpoint(&_ms);
	{
		dgame::PlayerManager players;
		players.addPlayer("KOTOTYT");
		ASSERT_EQ(players.size(), 1);
	}
	_CrtMemDumpAllObjectsSince(&_ms);
}

TEST(domino, PlayerManager_checkPlayer) {
	_CrtMemState _ms;
	_CrtMemCheckpoint(&_ms);
	{
		dgame::PlayerManager players;
		players.addPlayer("KOTOTYT");
		ASSERT_TRUE(players.checkPlayer("KOTOTYT"));
		ASSERT_FALSE(players.checkPlayer("LOL"));
		players.addPlayer("LOL");
		ASSERT_TRUE(players.checkPlayer("KOTOTYT"));
		ASSERT_TRUE(players.checkPlayer("LOL"));
		ASSERT_FALSE(players.checkPlayer("LOL2"));
	}
	_CrtMemDumpAllObjectsSince(&_ms);
}

TEST(domino, PlayerManager_playerExistingException) {
	_CrtMemState _ms;
	_CrtMemCheckpoint(&_ms);
	{
		dgame::PlayerManager players;
		players.addPlayer("KOTOTYT");
		ASSERT_TRUE(players.checkPlayer("KOTOTYT"));
		ASSERT_THROW(players.addPlayer("KOTOTYT"), dgame::PlayerExistingException);
		ASSERT_TRUE(players.checkPlayer("KOTOTYT"));
		ASSERT_FALSE(players.checkPlayer("MONO"));
		players.addPlayer("MONO");
		ASSERT_THROW(players.addPlayer("MONO"), dgame::PlayerExistingException);
		ASSERT_TRUE(players.checkPlayer("MONO"));
	}
	_CrtMemDumpAllObjectsSince(&_ms);
}

TEST(domino, PlayerManager_deletePlayer) {
	_CrtMemState _ms;
	_CrtMemCheckpoint(&_ms);
	{
		dgame::PlayerManager players;
		players.addPlayer("KOTOTYT");
		ASSERT_TRUE(players.checkPlayer("KOTOTYT"));
		ASSERT_EQ(players.size(), 1);
		players.deletePlayer("KOTOTYT");
		ASSERT_EQ(players.size(), 0);
		players.addPlayer("MONO");
		ASSERT_EQ(players.size(), 1);
		players.deletePlayer("MONO");
		ASSERT_EQ(players.size(), 0);
		players.addPlayer("KOTOTYT");
		players.addPlayer("MONO");
		ASSERT_EQ(players.size(), 2);
		players.deletePlayer("MONO");
		ASSERT_EQ(players.size(), 1);
	}
	_CrtMemDumpAllObjectsSince(&_ms);
}

TEST(domino, PlayerManager_getPlayer) {
	_CrtMemState _ms;
	_CrtMemCheckpoint(&_ms);
	{
		dgame::PlayerManager players;
		players.addPlayer("KOTOTYT");
		const dgame::Player *pl = players.getPlayer("KOTOTYT");
		ASSERT_EQ("KOTOTYT", pl->getName());
		ASSERT_EQ(0, pl->getScore());
		pl = players.getPlayer("HOME");
		ASSERT_EQ(NULL, pl);
	}
	_CrtMemDumpAllObjectsSince(&_ms);
}

TEST(domino, PlayerManager_operator_scope) {
	_CrtMemState _ms;
	_CrtMemCheckpoint(&_ms);
	{
		dgame::PlayerManager players;
		for (int i = 0; i < players.size(); i++)
		{
			const dgame::Player *pl = players[i];
			ASSERT_FALSE(pl == NULL);
		}
		players.addPlayer("KOTOTYT");
		players.addPlayer("Home");
		for (int i = 0; i < players.size(); i++)
		{
			const dgame::Player *pl = players[i];
			ASSERT_FALSE(pl == NULL);
		}
		ASSERT_EQ("KOTOTYT", players[0]->getName());
		ASSERT_EQ("Home", players[1]->getName());
	}
	_CrtMemDumpAllObjectsSince(&_ms);
}

TEST(domino, PlayerManager_operator_scope_outOfRangeException) {
	_CrtMemState _ms;
	_CrtMemCheckpoint(&_ms);
	{
		dgame::PlayerManager players;
		for (int i = 0; i < players.size(); i++)
		{
			const dgame::Player *pl = players[i];
			ASSERT_FALSE(pl == NULL);
		}
		players.addPlayer("KOTOTYT");
		players.addPlayer("Home");
		ASSERT_THROW(players[players.size() + 1], dgame::OutOfRangeException);
	}
	_CrtMemDumpAllObjectsSince(&_ms);
}

TEST(domino, PlayerManager_ActivePlayer) {
	_CrtMemState _ms;
	_CrtMemCheckpoint(&_ms);
	{
		dgame::PlayerManager players;
		ASSERT_TRUE(players.getActivePlayer() == NULL);
		players.addPlayer("KOTOTYT");
		const dgame::Player *pl = players.getActivePlayer();
		ASSERT_EQ(players.getActivePlayer()->getName(), "KOTOTYT");
		players.addPlayer("HOME");
		ASSERT_EQ(pl->getName(), "KOTOTYT");
		players.addPlayer("HOME2");
		ASSERT_EQ(players.getActivePlayer()->getName(), "KOTOTYT");
	}
	_CrtMemDumpAllObjectsSince(&_ms);
}

TEST(domino, PlayerManager_nextActivePlayer) {
	_CrtMemState _ms;
	_CrtMemCheckpoint(&_ms);
	{
		dgame::PlayerManager players;
		ASSERT_TRUE(players.getActivePlayer() == NULL);
		players.addPlayer("KOTOTYT");
		ASSERT_EQ(players.getActivePlayer()->getName(), "KOTOTYT");
		players.addPlayer("HOME");
		ASSERT_EQ(players.getActivePlayer()->getName(), "KOTOTYT");
		ASSERT_EQ(players.nextPlayer()->getName(), "HOME");
		ASSERT_EQ(players.getActivePlayer()->getName(), "HOME");
		players.addPlayer("TEST");
		ASSERT_EQ(players.nextPlayer()->getName(), "TEST");
		ASSERT_EQ(players.nextPlayer()->getName(), "KOTOTYT");
	}
	_CrtMemDumpAllObjectsSince(&_ms);
}

TEST(domino, PlayerManager_deleteActivePlayer) {
	_CrtMemState _ms;
	_CrtMemCheckpoint(&_ms);
	{
		dgame::PlayerManager players;
		ASSERT_TRUE(players.getActivePlayer() == NULL);
		players.addPlayer("KOTOTYT");
		ASSERT_EQ(players.getActivePlayer()->getName(), "KOTOTYT");
		players.addPlayer("HOME");
		ASSERT_EQ(players.getActivePlayer()->getName(), "KOTOTYT");
		players.deletePlayer("KOTOTYT");
		ASSERT_EQ(players.getActivePlayer()->getName(), "HOME");
		players.deletePlayer("HOME");
		ASSERT_TRUE(players.getActivePlayer() == NULL);
		players.addPlayer("KOTOTYT");
		players.addPlayer("HOME");
		players.addPlayer("HOME2");
		players.nextPlayer();
		players.nextPlayer();
		ASSERT_EQ(players.getActivePlayer()->getName(), "HOME2");
		players.deletePlayer("HOME2");
		ASSERT_EQ(players.getActivePlayer()->getName(), "KOTOTYT");
		players.deletePlayer("HOME");
		ASSERT_EQ(players.getActivePlayer()->getName(), "KOTOTYT");
		players.deletePlayer("KOTOTYT");
		ASSERT_TRUE(players.getActivePlayer() == NULL);
		ASSERT_EQ(players.size(), 0);
		ASSERT_TRUE(players.checkPlayer("KOTOTYT")==NULL);
	}
	_CrtMemDumpAllObjectsSince(&_ms);
}

namespace dgame
{
	class MyNextPlayer : public INextPlayer<MyNextPlayer>
	{
		virtual Player *nextPlayer(Player **players, int size, Player *activePlayer, void *data)
		{
			if(data != NULL)
			{
				Domino *lastMove = (Domino *)data; 
				if (lastMove->getLeft() == lastMove->getRight())
				{
					return activePlayer;
				}
			}
			StandartNextPlayer tmp;
			return tmp.nextPlayer(players, size, activePlayer, NULL);
		};
	};
}

TEST(domino, PlayerManager_nextPlayerOrDeleteWithMyRule) {
	_CrtMemState _ms;
	_CrtMemCheckpoint(&_ms);
	{
		dgame::PlayerManager players(new dgame::MyNextPlayer);
		ASSERT_TRUE(players.getActivePlayer() == NULL);
		players.addPlayer("KOTOTYT");
		ASSERT_EQ(players.getActivePlayer()->getName(), "KOTOTYT");
		players.addPlayer("HOME");
		ASSERT_EQ(players.getActivePlayer()->getName(), "KOTOTYT");
		players.deletePlayer("KOTOTYT");
		ASSERT_EQ(players.getActivePlayer()->getName(), "HOME");
		players.deletePlayer("HOME");
		ASSERT_TRUE(players.getActivePlayer() == NULL);
		players.addPlayer("KOTOTYT");
		players.addPlayer("HOME");
		players.addPlayer("HOME2");
		players.nextPlayer();
		players.nextPlayer();
		ASSERT_EQ(players.getActivePlayer()->getName(), "HOME2");
		players.nextPlayer(&dgame::Domino(0,0));
		//player must not changing, if we give DominoDouble
		ASSERT_EQ(players.getActivePlayer()->getName(), "HOME2");
		players.nextPlayer(&dgame::Domino(0,1));
		ASSERT_EQ(players.getActivePlayer()->getName(), "KOTOTYT");
		players.deletePlayer("HOME2");
		ASSERT_EQ(players.getActivePlayer()->getName(), "KOTOTYT");
		players.deletePlayer("HOME");
		ASSERT_EQ(players.getActivePlayer()->getName(), "KOTOTYT");
		players.deletePlayer("KOTOTYT");
		ASSERT_TRUE(players.getActivePlayer() == NULL);
		ASSERT_EQ(players.size(), 0);
		ASSERT_TRUE(players.checkPlayer("KOTOTYT")==NULL);
	}
	_CrtMemDumpAllObjectsSince(&_ms);
}